package handlers

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/RuiGuangServer/global"
	"github.com/RuiGuangServer/logs"
)

type VideoRecogManager struct {
	needsLightData bool
}

var videoRecogManager = &VideoRecogManager{}

// 消息类型定义 (根据交互文档)
const (
	Notify_ReqConfig      = iota // 请求配置信息和全部扫描信息 client--->server
	Notify_ResponseConfig        // 应答配置信息 server--->client
	Notify_Ping                  // 心跳包 client--->server
	Notify_Pong                  // 服务器应答Ping帧，server--->client
	Notify_RealData              // 服务器上传的实时数据，server---->client
	Notify_ReqReal               // 请求配置信息的实时值，client---->server
	Notify_ResponseReal          // 应答配置信息的实时值，server---->client
)

// VRHeader 协议头结构体 (根据交互文档)
type VRHeader struct {
	IMsgType uint16 // 包类型
	IReserve uint16 // 保留字段，默认为0
	Len      uint32 // 包的实际长度 (加密后的长度)
}

// RealDataItem 实时数据项 (根据交互文档)
type RealDataItem struct {
	Key   string `json:"key"`
	Name  string `json:"name"`
	Value string `json:"value"`
	Num   int    `json:"num"`
}

type VRConfig struct {
	Code      int    `json:"code"`
	Desc      string `json:"desc"`
	DataCofig []struct {
		Name string `json:"name"`
		Key  string `json:"key"`
		Num  int    `json:"num"`
	} `json:"dataCofig"`
	DataOcr []struct {
		Text string `json:"text"`
		Num  int    `json:"num"`
	} `json:"dataOcr"`
}

// CheckLenSum 校验长度值合规性 (根据交互文档)
func CheckLenSum(encryptedLen uint32) bool {
	// 将加密长度转换为字节数组
	bytes := make([]byte, 4)
	binary.BigEndian.PutUint32(bytes, encryptedLen)

	// 计算字节和并检查模256是否为0
	sum := int(bytes[0]) + int(bytes[1]) + int(bytes[2]) + int(bytes[3])
	return sum%0x100 == 0
}

// GetLenSum 计算通信用的长度字段 (根据交互文档)
func GetLenSum(actualLength int) uint32 {
	// 确保长度在有效范围内 (0-0xFFFFFF)
	if actualLength < 0 || actualLength > 0xFFFFFF {
		return 0
	}

	// 提取长度的三个字节
	byte1 := byte((actualLength >> 16) & 0xFF)
	byte2 := byte((actualLength >> 8) & 0xFF)
	byte3 := byte(actualLength & 0xFF)

	// 计算校验和
	sum := int(byte1) + int(byte2) + int(byte3)
	checksum := byte((0x100 - sum) & 0xFF)

	// 组合为4字节长度字段 (校验和 + 3字节长度)
	return uint32(checksum)<<24 | uint32(actualLength)
}

// ExtractActualLength 从加密长度中提取实际长度
func ExtractActualLength(encryptedLen uint32) int {
	// 取后3字节作为实际长度
	return int(encryptedLen & 0xFFFFFF)
}

// GetLightData 获取当前灯光数据
func GetLightData() {
	data, _ := global.LightData.Load().(map[string]*global.Listlight)
	if len(data) == 0 {
		videoRecogManager.needsLightData = true
	}
}

// MsgVR 创建视频识别请求消息 (根据交互文档)
func MsgVR(msgType int) []byte {
	buf := make([]byte, 8) // VRHeader 固定8字节

	// 设置消息类型
	binary.BigEndian.PutUint16(buf[0:2], uint16(msgType))

	// 保留字段设置为0
	binary.BigEndian.PutUint16(buf[2:4], 0)

	// 设置长度字段 (根据消息类型)
	var dataLength int
	switch msgType {
	case Notify_ReqConfig, Notify_Ping, Notify_ReqReal:
		// 这些消息没有数据体，长度为0
		dataLength = 0
	default:
		// 其他消息可能需要数据体
		dataLength = 0
	}

	// 计算并设置加密长度
	encryptedLen := GetLenSum(dataLength)
	binary.BigEndian.PutUint32(buf[4:8], encryptedLen)

	return buf
}

func parseVRHead(data []byte) (*VRHeader, error) {
	if len(data) < 8 {
		return nil, errors.New("incomplete header")
	}
	VRHead := &VRHeader{
		IMsgType: binary.BigEndian.Uint16(data[0:2]),
		IReserve: binary.BigEndian.Uint16(data[2:4]),
		Len:      binary.BigEndian.Uint32(data[4:8]),
	}

	// 验证长度字段的合理性
	if !CheckLenSum(VRHead.Len) {
		return nil, errors.New("invalid length checksum")
	}

	// 添加长度范围检查
	actualLength := ExtractActualLength(VRHead.Len)
	if actualLength > 1048576 { // 限制最大长度为1MB
		return nil, fmt.Errorf("message length too large: %d", actualLength)
	}

	return VRHead, nil
}

// HandleVideoRecog 处理视频识别消息
func HandleVideoRecog(data []byte, logger *logs.AsyncLogger, dataer *logs.AsyncLogger) error {
	// fmt.Printf("len: %v\n", len(data))
	// fmt.Printf("data: %v\n", data)
	// 检查数据长度是否足够解析头部
	if len(data) < 8 {
		return fmt.Errorf("insufficient data for header: expected 8 bytes, got %d", len(data))
	}

	hbuf := data[:8]
	// fmt.Printf("hbuf %v\n", hbuf)
	head, err := parseVRHead(hbuf)
	if err != nil {
		return fmt.Errorf("video processing error: %v", err)
	}
	// fmt.Printf("head %v\n", head)

	// 提取实际长度
	actualLength := ExtractActualLength(head.Len)

	// 验证消息长度
	if actualLength < 0 {
		return fmt.Errorf("invalid message length: %d", actualLength)
	}

	htype := int(head.IMsgType)
	// fmt.Printf("htype: %v\n", htype)
	// 检查是否有足够的正文数据
	expectedTotalLength := 8 + actualLength
	if len(data) < expectedTotalLength {
		return fmt.Errorf("incomplete message, expected %d bytes, got %d", expectedTotalLength, len(data))
	}

	// 提取正文
	body := data[8:expectedTotalLength]
	// fmt.Printf("body: %v\n", body)
	return handleMessage(htype, body, logger)
}

// handleMessage 处理具体消息类型 (根据交互文档)
func handleMessage(vtype int, body []byte, logger *logs.AsyncLogger) error {
	switch vtype {
	case Notify_ResponseConfig: // 应答配置信息
		var config VRConfig
		if err := json.Unmarshal(body, &config); err != nil {
			return fmt.Errorf("failed to parse config data: %v", err)
		}
		logger.Info("Received config: code=%d, desc=%s", config.Code, config.Desc)
		return nil

	case Notify_Pong: // 服务器应答Ping帧
		logger.Info("Received heartbeat response at %v", time.Now().Format("2006-01-02 15:04:05"))
		return nil

	case Notify_RealData: // 服务器上传的实时数据
		var items []RealDataItem
		if err := json.Unmarshal(body, &items); err != nil {
			return fmt.Errorf("failed to parse real-time data: %w", err)
		}

		for _, item := range items {
			if item.Key == "" {
				logger.Warn("Skipping item with empty key")
				continue
			}

			// 转换为Listlight格式并更新全局数据
			light := &global.Listlight{
				Key:   item.Key,
				Name:  item.Name,
				Value: item.Value,
				Num:   item.Num,
			}
			updateLightData(light)
		}

		logger.Info("Received real-time data: %d items", len(items))
		return nil

	case Notify_ResponseReal:
		var items []RealDataItem
		if err := json.Unmarshal(body, &items); err != nil {
			return fmt.Errorf("failed to parse real-time response: %w", err)
		}
		// fmt.Printf("items %v\n", items)
		// 转换为Listlight格式
		lights := make([]global.Listlight, 0, len(items))
		for _, item := range items {
			if item.Key == "" {
				logger.Warn("Skipping item with empty key")
				continue
			}

			lights = append(lights, global.Listlight{
				Key:   item.Key,
				Name:  item.Name,
				Value: item.Value,
				Num:   item.Num,
			})
		}

		updateAllLightData(lights, logger)
		logger.Info("Received light data: %d items", len(lights))
		return nil

	default:
		return fmt.Errorf("received unknown video recognition message type: %d", vtype)
	}
}

// updateLightData 更新单个灯光数据
func updateLightData(light *global.Listlight) {
	loadedData, ok := global.LightData.Load().(map[string]*global.Listlight)
	if !ok {
		loadedData = make(map[string]*global.Listlight)
	}

	newData := make(map[string]*global.Listlight, len(loadedData)+1)
	for k, v := range loadedData {
		newData[k] = v
	}
	newData[light.Key] = light
	global.LightData.Store(newData)
}

// updateAllLightData 更新所有灯光数据
func updateAllLightData(lights []global.Listlight, logger *logs.AsyncLogger) {
	newLightData := make(map[string]*global.Listlight, len(lights))

	for i := range lights {
		light := &lights[i]
		if light.Key == "" {
			logger.Warn("Skipping light entry with empty key at index %d", i)
			continue
		}
		newLightData[light.Key] = light
	}

	// 合并旧数据
	if oldData, ok := global.LightData.Load().(map[string]*global.Listlight); ok {
		for key, oldLight := range oldData {
			if _, exists := newLightData[key]; !exists {
				newLightData[key] = oldLight
			}
		}
	}

	global.LightData.Store(newLightData)
}

// CheckAndRequestLightData 检查并请求灯光数据
func CheckAndRequestLightData(sendFunc func([]byte) error, logger *logs.AsyncLogger) {
	if videoRecogManager.needsLightData {
		msg := MsgVR(Notify_ReqReal)
		if err := sendFunc(msg); err != nil {
			logger.Error("Failed to request light data: %v", err)
		} else {
			logger.Info("Requested light data")
			videoRecogManager.needsLightData = false
		}
	}
}
